Appearance
C# 由 C 和 C++ 衍生而来,优化了两者的安全性问题,如:鼠标状态读取、内存读写。 C# 需要依赖环境运行,如 .NET Framework(windows平台)、.NET Core(跨平台)。
数据类型
值类型
数据由二进制来转换单位,最小的单位是 '位' 。 不同的数据结构,占用的位数不同,位数越多该数据结构占用越大。
Bool(1位|布尔值):true/false 默认false
Byte(8位|字节):0 - 255 默认0
char(16位|Unicode字符):U+0000 - U+ffff 默认'/0'
double(64位|双精度浮点):(-7.9*10**28 - 7.9*10**28)/(10**0 - 10**28) 默认0.0D
float(32位|单精度浮点):(+/-)5.0*10**-324 - (+/-)1.7*10**308 默认0.0F
short(16位|有符号整数类型):-32,768 - 72,767 默认0
int(32位|有符号整数类型):-2,147,483,648 - 2,147,483,647 默认0
long(64位|有符号整数类型):-2^63 - 2^63-1 默认0枚举enum
一般用于定义类型 枚举是一组自定义名词的整形常量
cs
enum 枚举类型名
{
枚举值1,
枚举值2,
枚举值列表
}
// 使用
枚举值类型 变量名 = 枚举值类型.枚举值;结构体struct
结构体可以创建多个数据结构 类似对象的类型定义
cs
struct 结构体名词
{
public 类型 结构体元素1;
public 类型 结构体元素2;
}
// 使用1
结构体名词 变量名 = new 结构体名词();
变量.结构体元素1 = 值;
变量.结构体元素2 = 值;
// 使用2
结构体名词 变量名 = new 结构体名词
{
结构体元素1 = 值,
结构体元素2 = 值,
}运用 - 值类型的运算
运算主要分为数学运算、比较运算、逻辑运算。
cs
位运算 - 与运算(同位均为真,则为真)
// 001
int a = 1
// 010
int b = 2
// 000
a & b == 0
位运算 - 或运算(同位有真,则为真)
// 001
int a = 1
// 010
int b = 2
// 011
a | b == 3引用类型
字符串
字符串是一个类,因为c#的优化处理,所以不用new 单引号,字符 双引号,字符串
cs
string str = "abc";
str[索引] // 可以通过索引查看,但不能修改
str += "d"; // 可以+=运算cs
// 静态函数
String.Concat(string,string,...) // 返回:字符串,拼接
// 公共函数
.Contains(string); // 返回:布尔值,是否包含【某些】字符串
.Remove(int); // 返回:字符串,从索引【几】开始删除
.Remove(int,int); // 返回值:字符串,从索引【几】开始删除【几】位
.Substring(int); // 返回:字符串,从索引【几】开始获取
.Substring(int,int); // 返回:字符串,从索引【几】开始获取【几】位
.Insert(int,string); // 返回值:字符串,从索引【几】开始添加【某些】字符串
.Replace(string,string); // 返回值:字符串,将所有【某些】字符串替换成【某些】字符串
.Split(string); // 返回值:字符串[],将【某些】字符串视作分隔符字符串工具 StringBuilder
用于解决字符串改变时,旧字符的内存不会销毁的问题。
cs
StringBuilder 工具 = new StringBuilder(字符串);
工具.Append(字符串); // 追加
string 字符串 = 工具.ToString();
.Append() // 追加
.Insert() // 同字符串
.Remove()
.Replace()
.ToString() // 强制转换成字符串数组
创建后不能动态调整长度
类型[] 数组名 = new 类型[长度];
类型[] 数组名 = new 类型[长度]{元素1, 元素2, ..., 元素n};
类型[] 数组名 = {元素1, 元素2, ..., 元素n};
int[] age = new int[5]{1,2,3,4,5};
注:未定义元素时,元素为默认值;未定义长度时,长度为元素数。
注:元素数和长度不等时,报错。运用 - 二维数组
类型[,] 数组名 = new 类型[外层长度,内层长度]{数组1,数组2};
int[,] ages = new int[2,3]{{1,2,3}, {1,2,3}};类 class
类体现了编程的面向对象思想。 注:不同参数类型数量的方法,可以共存。
cs
class 类名
{
public 值类型 属性名;
public 返回值类型 方法名()
{
方法体;
this.属性;
this.方法(); // 可通过this关键字,调用实例的属性方法
}
}
// 调用 - 创建实例
类名 实例名 = new 类名();
实例名.属性名 = 值;
// 调用 - 创建并定义实例
类名 实例名 = new 类名()
{
属性名 = 值;
};
// 调用实例
实例名.属性;
实例名.方法();运用 - 类的属性私有化
用于封装属性值的读取和修改 一般名字和属性相同,首字母大写
cs
class 类名
{
private string name; // 修饰符要更改为私域
public string Name
{
get // 没有get方法则不可访问
{
return name;
return "私密信息不可访问" // 也可用于鉴权,等其他运算
}
set // 没有set方法则不可修改
{
subName = value; // value是关键字,表示被赋值的值
Console.WriteLine("狗贼xxx试图修改密码"); // 也可用于鉴权
}
}
}
// 简写
class 类名
{
private string name;
public string Name {get; set; } // 默认的改查方法,注:指向Name,而非name
public string Name {get; } // 只读
}运用 - 类的构造方法
构造方法名和类名相同 构造方法在实例创建的时候使用,并且没有返回值
cs
class 类名
{
public string name;
public 类名(name)
{
this.name = name
}
public 类名(形参): this(name) // 通过选择同样的参数名,实现重载
{
// 重载的代码
}
}
// 创建实例时,参数写在类名里
类名 实例名 = new 类名(实参);运用 - 类的析构 ~
析构方法名在类名前加波浪号,在实例被销毁时调用 一般用于清空,比如将某些引用类型的值赋值为null
cs
class 类名
{
public string name;
~类名()
{
Array = null;
name = null;
}
}运用 - 类的静态属性
通过关键字static修饰,给类添加属性方法,而不是给实例写属性方法 静态属性是class里唯一的
cs
class 类
{
public static 类型 静态属性名 = 值;
public static 返回值 静态方法名()
{
// 函数体
}
}
// 调用
类.静态属性名运用 - 静态类 static
通过关键字 static 修饰类 静态类里只能包含静态成员
cs
static class 类名
{
public static 类型 静态属性名 = 值;
static 类名() // 静态的构造方法不可有参数,只会在首次使用时调用
{
// 构造方法
// 一般用于给静态属性赋值
}
}运用 - 抽象类 abstract
通过关键字 abstract 修饰类 抽象类本身不可被构造,主要用于继承 可以理解成,把一些相同特质的类,抽象出一个父级来概括
cs
abstract class 抽象类
{
// code
public abstract void 抽象方法(); // 抽象方法没有函数体,一般被用于继承者重写
}
// 继承
class 子类:抽象类
{
public override void 重写() // 修饰符同虚方法,用于继承
{
// 函数体
}运用 - 类的继承
子类具备父类的全部内容,并且具备其独特的内容 例如:父类 - 家电,子类 - 冰箱
cs
class 子类: 父类
{
// 属性、 方法
base.方法(); // 可通过base关键字,调用父类方法
}
// 创建实例时,父类可以指向子类
父类 实例名 = new 子类();运用 - 类方法的重写(虚方法)
子类的方法和父类方法名相同
cs
// 通过关键字 new 来重写(不推荐)
class 父类
{
public void 方法名()
{
内容
}
}
class 子类: 父类
{
public new void 方法名()
{
内容
}
}
// 通过虚方法来重写
class 父类
{
public virtual void 方法名()
{
内容
}
}
class 子类: 父类
{
public override void 方法名()
{
base.方法(); // 可通过base关键字,调用父类原本方法,然后再添加新内容
内容
}
}接口 interface
包含事件、索引器、方法和属性,但不包含构造函数、析构函数、静态成员和常量。 接口负责定义,继承者负责实现(类似抽象)。 默认引用public
cs
interface 接口名
{
// 内容
}
// 继承
class 子类: 基类, 接口1, 接口2 // 如果有基类,必须放首位
{
// 内容
// 接口的实现
}类型转换
隐式转换 - 由小到大
主要看范围是否兼容转换前 位数从小到大可以正常转换,如 byte(8bit) -> int(32bit) √ 整数可以转换成小数,如 int -> double √ 有无符号不能正常转换,如 short(有符号) -> unit(无符号) ×
byte b = 10;
int i = b;
double d = i;强制转换 - 由大变小
一般用于范围由大变小,可能会丢失精度,需要调用方法强制转换。
方案1 - 通过括号快捷转换
int age = 100;
byte bage = (byte)age;
方案2 - 通过转换类Convert
int age = 100;
byte bage = Convert.ToByte(age);强制转换 - 字符串和整型
数字 -> 字符串,变量.ToString()方法 字符串 -> 数字,类型.Parse(目标)方法
cs
数字 -> 字符串
int age = 100;
string bage = age.ToString();
字符串 -> 数字
string str = 100;
int num = int.Parse(str);
注:不能转换时会报错强制转换 - 装箱与拆箱
值类型可以装箱成引用类型,如 int -> object 通过拆箱,可以将该引用类型重新转换回值类型。
装箱
int i = 3;
object o = i;
拆箱
int b = (int)o;变量
常量
运行时不可别改变。
整数:1
浮点:1.1f
字符:'a'
字符串:'abc'变量
运行时可被改变,需先被声明类型。
类型 变量名 = 值;
Byte x = 1;函数(静态)
cs
// 创建函数
static 返回值类型 方法名(参数类型 参数,参数2类型 参数2 = 缺省值)
{
函数体;
return 返回值;
}
// 调用方法
方法名(参数);
// 泛型运用 - 实参改变 ref
通过关键字修饰参数,将参数的值类型改成引用类型。 基于底层,作为参数的引用类型可在函数中改变。 例:可以用于交换这个场景。
cs
static 返回值类型 方法名(ref 参数类型 参数1,ref 参数2类型 参数2)
{
var 临时变量 = 参数1;
参数1 = 参数2;
参数2 = 临时变量;
}
// 调用
方法名(ref 参数1, ref 参数2);运用 - 光速赋值 out
通过关键字修饰参数,直接给实参赋值。 有点类似 变量 = 函数(变量) 的语法糖。
cs
static 返回值类型 方法名(out 参数类型 参数名)
{
out参数 = out值;
return 返回值;
}
// 调用
变量类型 变量名; // 可以不添加初始值
方法名(out 变量名) // 将函数的out值 赋值 给变量运用 - 泛型 T
通过标识符,来假定参数类型 例:可以用于交换这个场景(省略对类型的重载)
cs
static 返回值类型 方法名<T, 泛型2>(T 参数1, T 参数2, 泛型2 参数3) // 泛型名称自己定义
{
// 函数体
T newVal = 参数2;
参数2 = 参数1;
参数1 = newValue; // 如果用于交换,参数一般添加ref关键字
}
// 调用
方法<类型>(); // 可不写类型cs
// 对泛型的约束
static 返回值类型 方法名<T, U>(T 参数1, U 参数2)where T: struct
where U: class, new() // 多个泛型可以换行添加,多种约束可以逗号
{
// 内容
}
// 约束的类型
struct // 值类型(数字布尔值等)
class // 引用类型
new() // 具有一个无参数的构造方法
基类 // 参数是基类或其派生类
接口 // 实现了该接口的类型委托 delegate
通过关键字 delegate ,定义(委托)方法类型 委托用于解决,方法传递的问题 例:监听场景,主程序执行过程中,需要让某个组件执行异步函数
cs
// 1. 定义委托类型
public delegate void 委托类型();
// 2. 声明委托变量
委托类型 委托; // 声明空指向
委托类型 委托 = new 委托类型(方法名); // 声明并添加委托
委托类型 委托 = 方法名; // 声明并添加委托的语法糖
// 3. 保存方法;
委托 = 方法名; // 赋值
委托 += 方法名; // 追加委托,先调用之前的,再调用之后的
委托 -= 方法名; // 取消委托匿名委托
使用委托时,方法名省略的一种写法
cs
委托 += delegate(参数类型 参数,...){
// 函数体
}
// 语法糖,省略了关键字 和 参数类型
委托 += (参数1,...) => {
// 函数体
}
// 语法糖, 只有单个参数时,省略括号
委托 += 参数 => {
// 函数体
}事件声明 event
在声明委托变量时,通过添加关键词event,表示该委托是个事件 事件在非所在类中,不可赋值,不可调用(允许追加和减少)
cs
// 声明委托
public 委托类型 委托名;
// 声明事件
public event 委托类型 委托名;集合
集合类似于C#内置的构造函数。 实现了ICollection、Ilist、Ienumerable接口。 集合可以动态调整长度,元素的类型可不同(因此不安全)。 利用集合的方法来实现多种复杂的功能。
非泛型集合:System.Collections
泛型集合:System.Collections.Generic数组 ArrayList
cs
using System.Collections;
ArrayList 数组名 = new ArrayList();
.Add(追加元素); // push
.Insert(索引, 插入元素); // 插入
.Remove(删除元素); // 删除(首个对应元素)
.RemoveAt(索引); // 删除
.Clear(); // 清空
.Reverse(); // 反向排序
.Contains(查找元素); 返回值: bool // 查询是否存在数组泛型 List
限制了元素类型
cs
using System.Collections.Generic;
List 数组名<类型> = new List<类型>();堆栈 Stack
后进先出 常使用于,对顺序要求不严格的场景,例:只需遍历全部
cs
using System.Collections;
Stack 堆栈 = new Stack();
.Push(追加元素);
.Pop(); 返回值: object // 出栈,返回装箱的元素
.Peek(); 返回值: object // 查看
.Contains(查找元素); 返回值: bool // 查询是否存在
.Clear(); // 清空
.Count; // 长度堆栈泛型 Stack
限制了元素类型
cs
using System.Collections.Generic;
Stack 堆栈<类型> = new Stack<类型>();队列 Queue
先进先出 常用于,优化性能,例:关闭开启时非销毁创建,而是利用队列隐藏显示
cs
using System.Collections;
Queue 队列 = new Queue();
.Enqueue(追加元素); // 入列push
.Dequeue(); 返回值: object // 出列shift,返回第一个
.Peek(); 返回值: object // 查看
// 其他类似堆栈队列泛型 Queue
限制了元素类型
cs
using System.Collections.Generic;
Queue 队列<类型> = new Queue<类型>();哈希表 Hashtable
无序,键值对
cs
using System.Collections;
Hashtable ht = new Hashtalbe();
.Add(键, 值); // 追加
ht[键] = 值; // 增改
ht[键] // 查找对应值(无则返回null)
.Remove(键) // 删除
.ContainsKey(寻找键); 返回值: bool // 查询是否存在
.ContainsValue(寻找值); 返回值: bool // 查询是否存在
.Keys; 返回值: object[] // 键数组,可通过foreach循环
.Values; 返回值: object[] // 值数组,同上字典泛型 Dictionary
限制了元素类型 TryGetValue方法是字典独有的
cs
using System.Collections.Generic;
Dictionary 字典<键类型, 值类型> = new Dictionary<键类型, 值类型>();
// 字典[键] 的上位替代,解决因键不存在导致的报错 返回值: bool
值类型 value;
bool res = 字典.TryGetValue(键,out value);
if(res){
// 取值成功
}
else{
// 取值失败
}其他关键字
访问修饰符
在类的变量或方法前面添加修饰符
cs
class 类名
{
修饰符 类型 属性名;
}public最大级
该修饰符的范围最广 允许其他的代码块中都可以调用
private类级
仅在当前类里,可访问其中成员
protected类及子集
在当前类,及其子类中,允许访问其中成员
internal文件级
仅在当前文件中,可访问其中成员
命名空间
类似于作用域,用于解决名词重复的问题
cs
namespace 空间名称
{
// 代码
}
// 调用 - 在当前名称空间内创建另一个名词空间的类的实例
另一个空间.类名 实例名 = new 另一个空间.类名();
// 调用2(常用) - 在顶部使用using
using 另一个空间名词
类名 实例名 = new 类名();执行顺序
分支结构
cs
if(布尔值)
{语句}
else if(布尔值)
{语句}
else
{语句}
switch (reply)
{
case "消耗品":
{
return;
}
}循环
cs
while(终止条件)
{
语句
continue 跳出当次循环
break 跳出循环
}
do
{
语句
continue 跳出当次循环
break 跳出循环
}while(终止条件)
for(定义变量;终止条件;循环后执行)
{
语句
break 跳出循环
}
foreach(迭代元素类型或var 定义变量名 in 迭代集合)
{
语句
}常用方法
常用函数(控制台)
System.Console.Writeline()
作用:将参数打印至控制台
参数:需要打印的内容
System.Console.Read()
作用:读取用户输入在控制台的内容,输入一个字符后执行剩余代码
参数:/
System.Console.ReadLine()
作用:读取用户输入在控制台的内容,回车后执行剩余代码
参数:/
System.Console.ForegroundColor = ConsoleColor.颜色;
作用:改变控制台文字的颜色类型判断
cs
变量 is 类型 // 布尔值随机数 Random
cs
new Random().Next(5, 10); // 参数1,最小值;参数2,最大值休眠 Thread
cs
Thread.Sleep(1000); // 参数,毫秒